﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Markup;

namespace MCPlatform.Communicate.SerialPorts
{
    public class SerialPortComm : ISerialPort
    {
        //新建串口对象
        public SerialPort Conn { get; set; }

        public string DeviceName { get; set; } = string.Empty;

        public bool IsHex { get; set; } = false;
        public bool IsOpen
        {
            get { return Conn.IsOpen; }

        }

        private AutoResetEvent _waitHandle = new AutoResetEvent(false);

        //  public SerialComInfo SerialComInfo { get; set; }

        private string _strData = string.Empty;
        private byte[] _byteData = new byte[] { };

        protected NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
        public string ReceivedStr { get { return _strData; } }
        public byte[] ReceivedByte { get { return _byteData; } }


        public event Action<string> SerialReceivedDataEvent;

        public event Action<string> SerialReceivedDataEventByHex;


        string? mReply = null;

        string? hexReply = null;

        /// <summary>
        /// 传入串口参数
        /// </summary>
        /// <param name="portName">串口号</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="dataBits">数据位</param>
        /// <param name="stopBits">停止位</param>
        /// <param name="Parity">校验位</param>
        public SerialPortComm(SerialPort conn)
        {

            this.Conn = conn;

            DeviceName = conn.PortName;

            this.Conn.ErrorReceived += Conn_ErrorReceived;

            Conn.DataReceived += serialPort1_DataReceived;

            SerialReceivedDataEvent += RS232Helper_SerialReceivedDataEvent;

            SerialReceivedDataEventByHex += RS232Helper_SerialReceivedDataEventByHex;
        }

        private void Conn_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {

            logger.Fatal(e);
        }

        private void RS232Helper_SerialReceivedDataEventByHex(string obj)
        {
            if (string.IsNullOrWhiteSpace(obj))
            {
                return;
            }

            hexReply = obj;
            _waitHandle.Set();
        }

        private void RS232Helper_SerialReceivedDataEvent(string obj)
        {
            if (string.IsNullOrWhiteSpace(obj))
            {
                return;
            }

            mReply = obj;
            _waitHandle.Set();

        }




        /// <summary>
        /// 打开串口
        /// </summary>
        public void OpenSerialPort()
        {

            try
            {
                if (!Conn.IsOpen) Conn.Open();             
                logger.Info("打开端口");
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message);
            }





        }

        public void CloseSerialPort()
        {
            try
            {
                logger.Info("关闭端口");
                Conn.Close();
            }
            catch (Exception)
            {

                throw;
            }

        }

        /// <summary>
        /// 发送字符串数据
        /// </summary>
        /// <param name="sendString">字符串数组</param>
        public async Task SendData(params string[] sendString)
        {
            if (sendString != null)
            {
                foreach (string item in sendString)
                {
                    try
                    {
                        logger.Info($"发送数据：{item}");
                        Conn.WriteLine(item);
                        await Task.Delay(100);
                    }
                    catch (Exception)
                    {

                        throw;
                    }

                }


            }

        }

        /// <summary>
        /// 发送字符串数据
        /// </summary>
        /// <param name="sendString">字符串数组</param>
        public void SendData2(string[] sendString)
        {
            if (sendString != null)
            {
                string stringBuildr = string.Join(" ", sendString);
                logger.Info($"发送数据：{stringBuildr}");
                Conn.WriteLine(stringBuildr);
            }

        }
        public  void  SendData(string sendString)
        {

            try
            {
                logger.Info($"发送数据：{sendString}");
                Conn.WriteLine(sendString);               

            }
            catch (Exception ex)
            {
                logger.Error(ex);
               
            }           

        }

        public async Task SendData2ByHex(string[] sendString)
        {
            if (sendString != null)
            {
                IsHex = true;
                string stringBuildr = string.Join(" ", sendString);

                try
                {
                    string stringWithoutSpaces = stringBuildr.Replace(" ", "");
                    stringWithoutSpaces = stringBuildr.Replace("0x", "");
                    byte[] sendByte = StringToByteArray(stringWithoutSpaces);
                    if (sendByte != null)
                    {
                        // 将字节数组的16进制值转换为字符串
                        string hexString = BitConverter.ToString(sendByte).Replace("-", "");
                        logger.Info($"{Conn.PortName}发送数据：{hexString}");
                        Conn.Write(sendByte, 0, sendByte.Length);
                        await Task.Delay(1);    
                    }

                }
                catch (Exception ex)
                {
                    logger.Error(ex);
                    throw;
                }

            }

        }
        public void SendDataByHex(string hexData)
        {

            try
            {
                IsHex = true;
                byte[] sendByte = StringToByteArray(hexData);
                if (sendByte != null)
                {
                    logger.Info($"发送数据：{hexData}");
                    Conn.Write(sendByte, 0, sendByte.Length);
                }

            }
            catch (Exception ex)
            {
                logger.Error(ex);
                throw;
            }



        }



        byte[] StringToByteArray(string hex)
        {
            hex = hex.Replace(" ", "");
            if (hex.Length % 2 != 0)
            {
                hex = hex.Insert(hex.Length - 1, "0");
            }

            int length = hex.Length / 2;
            byte[] byteArray = new byte[length];

            try
            {
                for (int i = 0; i < length; i++)
                {
                    byteArray[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                throw;
            }

            return byteArray;
        }

        public async Task<string?> SendDataAndGetReply(string sendString)
        {
            try
            {
                IsHex = false;
                mReply = null;
                Conn.DiscardInBuffer();
                _waitHandle.Reset();

                logger.Info($"发送数据：{sendString}");

                 SendData(sendString);

                await Task.Delay(0);

                _waitHandle.WaitOne(5000);

                //await Task.Run(async () =>
                //{
                //    Stopwatch stopwatch = new Stopwatch();
                //    stopwatch.Restart();
                //    while ((mReply == null) && (stopwatch.Elapsed < TimeSpan.FromMilliseconds(2000)))
                //    {
                //        await Task.Delay(2);
                //    }


                //});


                if (mReply is null)
                {
                    logger.Error($"方法接收数据为空！");
                }
                else
                {
                    // logger.Info($"方法接收数据：{mReply}");
                }


                return mReply;

            }
            catch (Exception ex)
            {
                logger.Error(ex);
                return null;
            }
        }

        public async Task<string> SendDataAndGetReply(double timeSpan = 1000, params string[] sendString)
        {
            try
            {
                IsHex = false;
                mReply = null;
                Conn.DiscardInBuffer();
                _waitHandle.Reset();
                // 使用 LINQ 将 bool 数组转换为字符串数组

                string dataString = string.Join(" ", sendString);
                //logger.Info($"发送数据：{dataString}");

                SendData2(sendString);

                await Task.Delay(0);
                _waitHandle.WaitOne((int)timeSpan);

                //await Task.Run(async () =>
                //{
                //    Stopwatch stopwatch = new Stopwatch();
                //    stopwatch.Restart();
                //    while ((mReply == null) && (stopwatch.Elapsed < TimeSpan.FromMilliseconds(timeSpan)))
                //    {
                //        await Task.Delay(2);
                //    }


                //});


                if (mReply is null)
                {
                    logger.Error($"方法接收数据为空！");
                }
                else
                {
                    //logger.Info($"方法接收数据：{mReply}");
                }

                if (mReply is null)
                {
                    return string.Empty;
                }
                return mReply;

            }
            catch (Exception ex)
            {
                logger.Error(ex);
                return string.Empty;
            }
        }

     
        public async Task<string> SendDatasAndGetNumberReply(double timeSpan = 3000, params string[] sendString)
        {
            try
            {
                if (sendString != null)
                {
                    IsHex = false;
                    foreach (string item in sendString)
                    {
                        try
                        {
                            mReply = null;
                            Conn.DiscardInBuffer();
                            _waitHandle.Reset();

                            logger.Info($"发送数据：{item}");
                            Conn.WriteLine(item);

                            await Task.Delay(0);
                            _waitHandle.WaitOne((int)timeSpan);
                            //await Task.Run(async () =>
                            //{
                            //    Stopwatch stopwatch = new Stopwatch();
                            //    stopwatch.Restart();
                            //    while ((mReply == null) && (stopwatch.Elapsed < TimeSpan.FromMilliseconds(timeSpan)))
                            //    {
                            //        await Task.Delay(2);
                            //    }


                            //});


                            if (mReply is null)
                            {
                                logger.Error($"方法接收数据为空！");
                            }
                            else if (mReply.Any(char.IsDigit))
                            {
                                // logger.Info($"方法接收数据：{mReply}");
                                string result = mReply;
                                mReply = null;
                                return result;


                            }
                            else if (mReply.Contains("?"))
                            {
                                logger.Error($"方法接收数据错误：{mReply}");
                            }
                            else if (mReply.Contains(@">"))
                            {

                            }




                        }
                        catch (Exception ex)
                        {
                            logger.Error(ex);
                            throw;
                        }

                    }


                }


                mReply = null;
                return string.Empty; ;

            }
            catch (Exception ex)
            {
                logger.Error(ex);
                mReply = null;
                return string.Empty;
            }
        }


        public async Task<string> SendDatasAndGetReply(double timeSpan = 3000, params string[] sendString)
        {
            try
            {
                if (sendString != null)
                {
                    IsHex = false;
                    for (int i = 0; i < sendString.Length; i++)
                    {
                        try
                        {
                            mReply = null;
                            Conn.DiscardInBuffer();
                            _waitHandle.Reset();

                            logger.Info($"发送数据：{sendString[i]}");
                            Conn.WriteLine(sendString[i]);

                            await Task.Delay(0);
                            _waitHandle.WaitOne((int)timeSpan);

                            //await Task.Run(async () =>
                            //{
                            //    Stopwatch stopwatch = new Stopwatch();
                            //    stopwatch.Restart();
                            //    while ((mReply == null) && (stopwatch.Elapsed < TimeSpan.FromMilliseconds(timeSpan)))
                            //    {
                            //        await Task.Delay(2);
                            //    }


                            //});


                            if (mReply is null)
                            {
                                logger.Error($"接收数据为空！");
                                return "false";
                            }
                            else if (mReply.Contains("?"))
                            {
                                logger.Error($"接收数据错误：{mReply}");
                                return "false";
                            }
                            else
                            {
                                // logger.Info($"方法接收数据：{mReply}");

                                if (i == sendString.Length - 1)
                                {
                                    return "true";
                                }
                            }


                        }
                        catch (Exception ex)
                        {
                            logger.Error(ex);
                            throw;
                        }
                    }



                }

                return "false";

            }
            catch (Exception ex)
            {
                logger.Error(ex);
                return string.Empty;
            }
        }

        public async Task<string> SendDataByHexAndGetReply(double timeSpan = 1000, params string[] sendString)
        {
            try
            {
                IsHex = true;

                Conn.DiscardInBuffer();

                _waitHandle.Reset();

                hexReply = null;

                await SendData2ByHex(sendString);


                bool handleState = _waitHandle.WaitOne((int)timeSpan);

                if (hexReply is null)
                {
                    logger.Error($"{Conn.PortName}接收数据为空！");
                }
                else
                {
                    //logger.Info($"接收数据：{mReply}");
                }

                if (hexReply is null)
                {
                    return string.Empty;
                }

                return hexReply;


            }
            catch (Exception ex)
            {
                logger.Error(ex);
                return string.Empty;
            }
            
        }

        private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);

        TaskCompletionSource<byte[]?> tcs = new TaskCompletionSource<byte[]?>();  
        public async Task<string?> SendAndReceiveAsync( TimeSpan timeout, params string[] sendString)
        {
            

            // 获取信号量，确保一次只有一个发送-接收操作
            await _semaphore.WaitAsync();

            tcs = new TaskCompletionSource<byte[]?>();

            try
            {
                // 发送数据
                await SendData2ByHex(sendString);

                // 设置超时回调
                var timer = new Timer(_ => tcs.TrySetResult(null), null, timeout, Timeout.InfiniteTimeSpan);

                // 等待接收数据或超时
               var receivedData = await tcs.Task;

                if (receivedData is null)
                {
                    return null;
                }

                // 取消超时定时器
                timer.Dispose();

                return BitConverter.ToString(receivedData).Replace("-", " "); ;
            }
            finally
            {
                // 释放信号量，允许下一次发送-接收操作
                _semaphore.Release();
               
            }
        }
        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;

            List<byte> tempBytes = new List<byte>();
            while (sp.BytesToRead > 0)
            {

                byte[] buffer = new byte[sp.BytesToRead];
                sp.Read(buffer, 0, buffer.Length);
                tempBytes.AddRange(buffer);
               
                Thread.Sleep(20);//超时时间
            }
            byte[] dataBuf = tempBytes.ToArray();

            if (dataBuf.Length > 0)
            {
               

                // 处理接收到的数据
                string receivedData = Encoding.UTF8.GetString(dataBuf);

               
                // 进行处理...
                //先判断是否是16进制

                string hexData = BitConverter.ToString(dataBuf).Replace("-", " ");
               // logger.Info($"接收16进制数据：{hexData}");
               // SerialReceivedDataEventByHex?.Invoke(hexData);
                if (IsHex)
                {
                    logger.Info($"{Conn.PortName}接收16进制数据：{hexData}");
                    SerialReceivedDataEventByHex?.Invoke(hexData);
                }
                else
                {
                    logger.Info($"{Conn.PortName}接收数据：{receivedData}");
                    SerialReceivedDataEvent?.Invoke(receivedData);//触发接收事件给上层
                }


                tcs.TrySetResult(dataBuf);
            }

        }





        private  void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort serialPort = (SerialPort)sender;

            // 读取接收缓冲区中的所有字节
            int bytesToRead = serialPort.BytesToRead;
            byte[] buffer = new byte[bytesToRead];
            serialPort.Read(buffer, 0, bytesToRead);

            // 将接收到的字节转换为16进制表示
            string hexData = BitConverter.ToString(buffer).Replace("-", " ");

            SerialReceivedDataEventByHex?.Invoke(hexData);


        }

      

    }
}

